/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* includes (local) ----------------------------------------------------------*/
#include <vfs_littlefs.h>
#include <vfs.h>
/* includes (standard library, system) ---------------------------------------*/
#include <string.h>
#include <stdio.h>
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_module.h>
#include <hal_mtd.h>

/* defines -------------------------------------------------------------------*/

#define READ_SIZE      16
#define PROG_SIZE      16
#define BLOCK_SIZE     4096
#define BLOCK_COUNT    128
#define CACHE_SIZE     16
#define LOOKAHEAD_SIZE 16
#define BLOCK_CYCLES   500

/* typedefs ------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables (extern) --------------------------------------------------------*/
/* variables (local) ---------------------------------------------------------*/

static hal_mtd_t *mtd = NULL;

/* variables (global) --------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/

static int mock_littlefs_read(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off,
                              void *buffer, lfs_size_t size)
{
    size_t addr = block * (cfg->block_size) + off;
    hal_mtd_read(mtd, addr, size, buffer);

    return LFS_ERR_OK;
}

static int mock_littlefs_prog(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off,
                              const void *buffer, lfs_size_t size)
{
    size_t addr = block * (cfg->block_size) + off;
    hal_mtd_write(mtd, addr, size, buffer);

    return LFS_ERR_OK;
}

static int mock_littlefs_erase(const struct lfs_config *cfg, lfs_block_t block)
{
    return LFS_ERR_OK;
}

static int mock_littlefs_sync(const struct lfs_config *cfg)
{
    return LFS_ERR_OK;
}

static struct lfs_config s_config = {
    // block device operations
    .read = mock_littlefs_read,
    .prog = mock_littlefs_prog,
    .erase = mock_littlefs_erase,
    .sync = mock_littlefs_sync,

    // block device configuration
    .read_size = READ_SIZE,
    .prog_size = PROG_SIZE,
    .block_size = BLOCK_SIZE,
    .block_count = BLOCK_COUNT,
    .cache_size = CACHE_SIZE,
    .lookahead_size = LOOKAHEAD_SIZE,
    .block_cycles = BLOCK_CYCLES,
};

int mock_littlefs_init(void)
{
    mtd = hal_mtd_open("ram");
    if (mtd == NULL) {
        return -1;
    }

    s_config.block_count = mtd->total_size / BLOCK_SIZE;

    (void)littlefs_init();
    if (littlefs_mount("/littlefs/", &s_config) != 0) {
        hal_mtd_close(mtd);
        mtd = NULL;
        return -1;
    }

    return 0;
}

int mock_littlefs_exit(void)
{
    if (mtd == NULL) {
        return -1;
    }
    if (littlefs_unmount("/littlefs/") != 0) {
        return -1;
    }
    littlefs_exit();
    mtd = NULL;
    return 0;
}
